using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace BoringTodo
{
    /// <summary>
    /// 处理窗体在高DPI显示设置下的缩放问题
    /// </summary>
    public static class DpiHandler
    {
        // P/Invoke声明
        [DllImport("user32.dll")]
        private static extern IntPtr GetDC(IntPtr hWnd);

        [DllImport("user32.dll")]
        private static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);

        [DllImport("gdi32.dll")]
        private static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
        
        [DllImport("user32.dll")]
        private static extern bool SetProcessDPIAware();

        private const int LOGPIXELSX = 88;
        private const int LOGPIXELSY = 90;

        // 当前系统的DPI缩放因子
        public static float DpiScaleFactorX { get; private set; } = 1.0f;
        public static float DpiScaleFactorY { get; private set; } = 1.0f;

        /// <summary>
        /// 初始化DPI缩放因子
        /// </summary>
        static DpiHandler()
        {
            // 设置进程为DPI感知
            try
            {
                SetProcessDPIAware();
            }
            catch
            {
                // 忽略可能的异常
            }
            
            // 获取当前系统的DPI设置
            IntPtr desktopDC = GetDC(IntPtr.Zero);
            if (desktopDC != IntPtr.Zero)
            {
                try
                {
                    int dpiX = GetDeviceCaps(desktopDC, LOGPIXELSX);
                    int dpiY = GetDeviceCaps(desktopDC, LOGPIXELSY);

                    // 计算缩放因子（相对于标准DPI 96）
                    DpiScaleFactorX = dpiX / 96.0f;
                    DpiScaleFactorY = dpiY / 96.0f;
                }
                finally
                {
                    ReleaseDC(IntPtr.Zero, desktopDC);
                }
            }
        }

        /// <summary>
        /// 为窗体启用DPI感知
        /// </summary>
        /// <param name="form">要启用DPI感知的窗体</param>
        public static void EnableDpiAwareness(Form form)
        {
            // 设置自动缩放模式为DPI
            form.AutoScaleMode = AutoScaleMode.Dpi;
            
            // 添加窗体加载事件处理程序
            form.Load += (s, e) => AdjustFormForDpi(form);
            
            // 强制设置窗体大小，以防止自动缩放导致的过大问题
            form.Load += (s, e) => {
                // 根据DPI缩放因子调整窗体大小
                if (DpiScaleFactorX > 1.0f)
                {
                    form.ClientSize = new Size(
                        (int)(form.ClientSize.Width / DpiScaleFactorX),
                        (int)(form.ClientSize.Height / DpiScaleFactorY)
                    );
                }
            };
        }

        /// <summary>
        /// 根据当前DPI设置调整窗体
        /// </summary>
        /// <param name="form">要调整的窗体</param>
        public static void AdjustFormForDpi(Form form)
        {
            // 根据DPI缩放因子调整窗体大小
            form.SuspendLayout();

            // 确保控件适应DPI变化
            foreach (Control control in form.Controls)
            {
                // 调整字体大小
                AdjustControlForDpi(control);
            }

            form.ResumeLayout();
        }

        /// <summary>
        /// 递归调整控件以适应DPI设置
        /// </summary>
        /// <param name="control">要调整的控件</param>
        private static void AdjustControlForDpi(Control control)
        {
            // 调整字体大小
            if (control.Font != null)
            {
                // 仅当缩放比例不是1.0时才调整字体
                if (Math.Abs(DpiScaleFactorX - 1.0f) > 0.01)
                {
                    float fontSize = control.Font.SizeInPoints;
                    control.Font = new Font(control.Font.FontFamily, fontSize, control.Font.Style);
                }
            }

            // 针对DataGridView特殊处理
            if (control is DataGridView dgv)
            {
                // 调整行高，防止在高DPI下过高
                dgv.RowTemplate.Height = (int)(dgv.RowTemplate.Height / DpiScaleFactorY);
                
                // 调整列宽
                foreach (DataGridViewColumn col in dgv.Columns)
                {
                    if (col.Width > 0)
                    {
                        col.Width = (int)(col.Width / DpiScaleFactorX);
                    }
                }
            }

            // 递归处理子控件
            foreach (Control child in control.Controls)
            {
                AdjustControlForDpi(child);
            }
        }

        /// <summary>
        /// 修复窗体大小，基于原始设计尺寸和当前DPI
        /// </summary>
        /// <param name="form">要修复的窗体</param>
        /// <param name="designWidth">设计时的宽度</param>
        /// <param name="designHeight">设计时的高度</param>
        public static void FixFormSize(Form form, int designWidth, int designHeight)
        {
            // 应用设计时的尺寸，而不是让系统根据DPI自动缩放
            form.ClientSize = new Size(designWidth, designHeight);
        }

        /// <summary>
        /// 防止截图后窗体大小发生变化
        /// </summary>
        /// <param name="form">要保持大小的窗体</param>
        /// <param name="originalSize">原始窗体大小</param>
        public static void PreserveFormSize(Form form, Size originalSize)
        {
            if (form.Size != originalSize)
            {
                form.Size = originalSize;
            }
        }
    }
} 